﻿/*
 * 由SharpDevelop创建。
 * 用户： Administrator
 * 日期: 2017/6/27
 * 时间: 0:13
 * 
 * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
 */
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

namespace TIDTool
{
	/// <summary>
	/// TidFileReader类<br/>
	/// 用于读取tid文件
	/// </summary>
	public class TidFileReader
	{
		public string fileName;
		public TidFile tidFile;
		
		public TidFileReader(string filename)
		{
			fileName = filename;
			tidFile = new TidFile();
		}
		
		public void ReadAll()
		{
			FileStream stream = new FileStream(fileName, FileMode.Open);
			int fileLength = (int)stream.Length;
			BinaryReader br = new BinaryReader(stream);
			
			// 先读取文件头，从中提取起始文件号（小端）和公共音频信息的偏移（大端）
			byte[] headerBytes = br.ReadBytes(256);
			int beginNumber = headerBytes[0x7c] + 
				headerBytes[0x7c+1]*256 + 
				headerBytes[0x7c+2]*256*256 + 
				headerBytes[0x7c+3]*256*256*256;
			int positionsOffset = headerBytes[0x84]*256*256*256 + 
				headerBytes[0x84+1]*256*256 + 
				headerBytes[0x84+2]*256 + 
				headerBytes[0x84+3];
			
			byte[] headerTextBytes = new byte[TidFile.HeaderText.Length];
			Array.Copy(headerBytes, headerTextBytes, TidFile.HeaderText.Length);
			tidFile.headerText = Encoding.UTF8.GetString(headerTextBytes);
			tidFile.BeginNumber = beginNumber;
//			tidFile.PositionsOffset = positionsOffset;
			
			// 然后读取私有音频信息索引区
			stream.Seek(0x110, SeekOrigin.Begin);
			byte[] posHeaderBytes = br.ReadBytes(8);
			long posCount = posHeaderBytes[3]*256*256*256 + 
				posHeaderBytes[2]*256*256 + 
				posHeaderBytes[1]*256 + 
				posHeaderBytes[0];
			long firstNumber = posHeaderBytes[7]*256*256*256 + 
				posHeaderBytes[6]*256*256 + 
				posHeaderBytes[5]*256 + 
				posHeaderBytes[4];
			
			List<int> contentInfos = new List<int>();
			byte[] posContentBytes = br.ReadBytes((int)posCount * 7);
			for (int i = 0; i < posCount * 7; i += 7)
			{
				long contentOffset = 0;
				if (posContentBytes[i] == 0x01 && 
				    posContentBytes[i+1] == 0x01 && 
				    posContentBytes[i+2] == 0x00 && 
				    posContentBytes[i+3] == 0x00)
				{
					contentOffset = posContentBytes[i+4]*256*256 + 
						posContentBytes[i+5]*256 + 
						posContentBytes[i+6];
//					continue;
				}
				else if (posContentBytes[i] == 0xFF && 
				    posContentBytes[i+1] == 0xFF && 
				    posContentBytes[i+2] == 0xFF && 
				    posContentBytes[i+3] == 0xFF)
				{
					contentOffset = -1;
//					continue;
				}
				else
				{
					System.Windows.Forms.MessageBox.Show("asd:" + i.ToString());
					continue;
				}
				contentInfos.Add((int)contentOffset);
			}
			
			// 根据前一步得到的索引，从后面的私有音频信息区提取每个音频的偏移和大小，并提取音频文件内容放到Dictionary的value中
			long oneNumber = firstNumber;
			foreach (int oneOffset in contentInfos)
			{
				if (oneOffset == -1)
				{
					TidPosition pos111 = new TidPosition((int)-1, (int)-1, (int)-1);
					tidFile.PrivateInfoIndex.Add(pos111);
					continue;
				}
				stream.Seek(oneOffset, SeekOrigin.Begin);
				byte[] oneBytes = br.ReadBytes(8);
				long fileOffset = oneBytes[0]*256*256*256 + 
					oneBytes[1]*256*256 + 
					oneBytes[2]*256 + 
					oneBytes[3];
				long fileLen = oneBytes[4]*256*256*256 + 
					oneBytes[5]*256*256 + 
					oneBytes[6]*256 + 
					oneBytes[7];
				TidPosition pos = new TidPosition((int)oneNumber, (int)fileOffset, (int)fileLen);
				tidFile.PrivateInfoIndex.Add(pos);
				if (fileOffset != 0xFFFFFFFF)
				{
//					tidFile.Positions.Add(pos);
					if (tidFile.PrivateFileList.ContainsKey(pos) == false)
					{
						stream.Seek(pos.beginOffset, SeekOrigin.Begin);
						byte[] fileBytes = br.ReadBytes(pos.fileLength);
						tidFile.PrivateFileList.Add(pos, fileBytes);
					}
				}
				else
				{
					continue;
				}
				oneNumber++;
			}
			
			// 提取公共音频信息区的每个音频文件的偏移和大小，并提取音频文件内容放到Dictionary的value中
			long onePublicNumber = beginNumber;
			stream.Seek(positionsOffset, SeekOrigin.Begin);
			byte[] positionsBytes = br.ReadBytes(fileLength - positionsOffset);
			for (int i = 0; i < positionsBytes.Length; i += 8, onePublicNumber++)
			{
				if (positionsBytes[i] == 0xFF && 
				    positionsBytes[i+1] == 0xFF && 
				    positionsBytes[i+2] == 0xFF && 
				    positionsBytes[i+3] == 0xFF)
				{
					TidPosition pos111 = new TidPosition((int)-1, (int)-1, (int)-1);
					tidFile.PublicInfoIndex.Add(pos111);
					continue;
				}
				long fileOffset = positionsBytes[i]*256*256*256 + 
					positionsBytes[i+1]*256*256 + 
					positionsBytes[i+2]*256 + 
					positionsBytes[i+3];
				long fileLen = positionsBytes[i+4]*256*256*256 + 
					positionsBytes[i+5]*256*256 + 
					positionsBytes[i+6]*256 + 
					positionsBytes[i+7];
				TidPosition pos = new TidPosition((int)onePublicNumber, (int)fileOffset, (int)fileLen);
				tidFile.PublicInfoIndex.Add(pos);
				if (fileOffset != 0xFFFFFFFF)
				{
//					tidFile.Positions.Add(pos);
					if (tidFile.PublicFileList.ContainsKey(pos) == false)
					{
						stream.Seek(pos.beginOffset, SeekOrigin.Begin);
						byte[] fileBytes = br.ReadBytes(pos.fileLength);
						tidFile.PublicFileList.Add(pos, fileBytes);
					}
				}
				else
				{
					continue;
				}
			}
			
			br.Close();
		}
	}
}
